﻿[assembly: System.Web.UI.WebResource("BM.Tools.WebControls.MForm.Controls.Validators.RootValidator.js", "application/x-javascript")]
[assembly: System.Web.UI.WebResource("BM.Tools.WebControls.MForm.Controls.Validators.RootValidator.debug.js", "application/x-javascript")]

namespace BM.Tools.WebControls.MForm.Controls
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;    
    using System.Linq;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    using AjaxControlToolkit;
    using BM.Tools.WebControls.MForm.Controls.Validators;
    using BM.Tools.WebControls.MForm.ScriptReferences;

    /// <summary>
    /// The validator class for the Root control
    /// </summary>    
    [ClientScriptResource("BM.Tools.WebControls.MForm",
            "BM.Tools.WebControls.MForm.Controls.Validators.RootValidator.js")]
    public class RootValidator : BaseValidator, IScriptControl
    {
        private Collection<ErrorCause> errorCauses = new Collection<ErrorCause>();               

        /// <summary>
        /// Gets the offspring items that reported the error.
        /// </summary>
        public Collection<ErrorCause> ErrorCauses
        {
            get
            {
                return errorCauses;
            }                 
        }

        /// <summary>
        /// Gets the Root control.
        /// </summary>
        public Root Root
        {
            get
            {
                return NamingContainer.FindControl(ControlToValidate) as Root;
            }
        }

        /// <summary>
        /// Gets a collection of script descriptors that represent ECMAScript (JavaScript) client components.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerable"/> collection of <see cref="T:System.Web.UI.ScriptDescriptor"/> objects.
        /// </returns>
        public IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            var descriptor = new ScriptControlDescriptor("BM.RootValidator", ClientID);
            descriptor.AddProperty("rootId", Root.ClientID);
            yield return descriptor;
        }

        /// <summary>
        /// Gets a collection of <see cref="T:System.Web.UI.ScriptReference"/> objects that define script resources that the control requires.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerable"/> collection of <see cref="T:System.Web.UI.ScriptReference"/> objects.
        /// </returns>
        public IEnumerable<ScriptReference> GetScriptReferences()
        {
            return null;
        }

        /// <summary>
        /// Determines if the validator is bound to a root control
        /// </summary>        
        /// <returns>
        /// true if the root is not null
        /// </returns>                
        protected override bool ControlPropertiesValid()
        {
            return Root != null;
        }

        /// <summary>
        /// checks validity of the root
        /// </summary>
        /// <returns>
        /// is data inside root control valid
        /// </returns>
        protected override bool EvaluateIsValid()
        {
            if (Root.Items.Any(item => item.Validate(this) == false))
            {
                ErrorMessage = string.Concat(ErrorCauses.Select(errorCause => errorCause.ErrorText).ToArray());
                return false;
            }

            return true;
        }

        /// <summary>
        /// includes scripts
        /// </summary>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            var scriptManager = ScriptManager.GetCurrent(Page);
            if (scriptManager == null)
            {
                throw new InvalidOperationException("The RootValidator control cannot work without the ASP.NET ScriptManager control used on a page.");
            }

            scriptManager.RegisterScriptControl(this);
            ScriptIncluder.IncludeResources(this);           
        }

        /// <summary>
        /// renders the control
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        protected override void Render(HtmlTextWriter writer)
        {
            if (DesignMode)
            {
                return;
            }

            var scriptManager = ScriptManager.GetCurrent(Page);                  
            scriptManager.RegisterScriptDescriptors(this);

            // reset ControlToValidate before render to prevent Microsoft's ValidatorHookupControl 
            // which would fire the RootValidator on the client side for all the constraints
            ControlToValidate = string.Empty;

            base.Render(writer);            
        }        
    }
}